package com.sinodata.bsm.cicp.service;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.MessageDispatcherImpl;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.mp.MPv3;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.TcpAddress;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;

import com.sinodata.bsm.common.vo.Trap;

public class ReceiveTrapService implements CommandResponder {

    public static ReceiveTrapService instance = null;

    private static Logger logger = Logger.getLogger("traplog");

    private MultiThreadedMessageDispatcher dispatcher;
    private Snmp snmp = null;
    private Address listenAddress;
    private ThreadPool threadPool;
    private final Map<String, List<Trap>> trapMap = new HashMap<String, List<Trap>>();
    private static Properties prop = null;

    private ReceiveTrapService() {
        this.run();
    }

    private void init() throws UnknownHostException, IOException {

        threadPool = ThreadPool.create("Trap", 2);
        dispatcher = new MultiThreadedMessageDispatcher(threadPool, new MessageDispatcherImpl());
        listenAddress = GenericAddress.parse(System.getProperty("snmp4j.listenAddress", prop.getProperty("snmp4j.listenAddress"))); // 本地IP与监听端口  
        TransportMapping transport;
        if (listenAddress instanceof UdpAddress) {
            transport = new DefaultUdpTransportMapping((UdpAddress) listenAddress);
        } else {
            transport = new DefaultTcpTransportMapping((TcpAddress) listenAddress);
        }
        snmp = new Snmp(dispatcher, transport);
        snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());
        snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
        snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3());
        USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
        SecurityModels.getInstance().addSecurityModel(usm);
        snmp.listen();
    }

    private void run() {
        try {
            init();
            snmp.addCommandResponder(this);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /** 
     * 
     * 实现CommandResponder的processPdu方法, 用于处理传入的请求、PDU等信息 
     * 当接收到trap时，会自动进入这个方法 
     *  
     * @param respEvnt 
     * 
     */
    @Override
    public void processPdu(CommandResponderEvent respEvnt) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (respEvnt != null && respEvnt.getPDU() != null) {
            Trap trap = new Trap();
            trap.setSource(respEvnt.getPeerAddress().toString().split("/")[0]);
            trap.setTimestamp(format.format(new Date()));
            trap.setSecurityLevel(respEvnt.getSecurityLevel());
            trap.setSecurityModel(respEvnt.getSecurityModel());
            trap.setCommutity(new OctetString(respEvnt.getSecurityName()).toString());
            trap.setPDUMessage(respEvnt.getPDU().getVariableBindings().toString());
            logger.info("源IP: " + trap.getSource() + "; \\t 时间戳： " + trap.getTimestamp());
            logger.info(trap.getPDUMessage());
            if (trapMap.containsKey(trap.getSource())) {
                trapMap.get(trap.getSource()).add(trap);
            } else {
                List<Trap> trapList = new ArrayList<Trap>();
                trapList.add(trap);
                trapMap.put(trap.getSource(), trapList);
            }
        }
    }

    public static ReceiveTrapService getInstance() {
        try {
            if (prop == null) {
                prop = new Properties();
                InputStreamReader isr = new InputStreamReader(new FileInputStream("cicp-conf/trap-cicp.properties"));
                prop.load(isr);
                isr.close();
            }
            if (prop.getProperty("start").trim().equalsIgnoreCase("true")) {
                if (instance == null) {
                    instance = new ReceiveTrapService();
                }
                return instance;
            }
            return null;
        } catch (Exception e) {
            logger.debug("trap配置文件未找到", e);
            return null;
        }
    }

    public List<Trap> getTrapsByIp(String ip) {
        System.out.println(trapMap.size());
        List<Trap> traps = trapMap.get(ip);
        trapMap.remove(ip);
        return traps;
    }

    public static void main(String[] args) {
        getInstance();
    }
}
